﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace iNet.Collections
{
	/// <summary>
	/// 提供集合相關功能。
	/// </summary>
	public unsafe static class CollectionUtility
	{
		#region BinarySearch
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <param name="list">指定的清單。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="comparer">提供比較元素大小的 IComparer&lt;T&gt; 介面，若元素型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)，或元素型別未實作 IComparable 介面，且 comparer 為 Null (Visual Basic 為 Nothing)。</exception>
		public static int BinarySearch<T>(this IList<T> list, T value, IComparer<T> comparer)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (list.Count == 0)
				return -1;

			//搜尋
			return BinarySearch<T>(list, 0, list.Count, value, comparer);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <typeparam name="TItem">清單元素的型別。</typeparam>
		/// <typeparam name="TValue">搜尋目標的型別。</typeparam>
		/// <param name="list">指定的清單。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="converter">將清單元素轉換成目標值的方法。</param>
		/// <param name="comparer">比較目標值大小的 IComparer&lt;TValue&gt; 介面，若目標值型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing) -或- converter 為 Null (Visual Basic 為 Nothing) -或- 目標值型別未實作 IComparable 介面，且 comparer 為 Null (Visual Basic 為 Nothing)。</exception>
		public static int BinarySearch<TItem, TValue>(this IList<TItem> list, TValue value, Func<TItem, TValue> converter, IComparer<TValue> comparer)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (list.Count == 0)
				return -1;

			//搜尋
			return BinarySearch<TItem, TValue>(list, 0, list.Count, value, converter, comparer);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <param name="list">指定的清單。</param>
		/// <param name="index">搜尋範圍的起始索引值。</param>
		/// <param name="count">搜尋範圍的元素個數。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="comparer">提供比較元素大小的 IComparer&lt;T&gt; 介面，若元素型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)，或元素型別未實作 IComparable 介面，且 comparer 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index 或 count 超出有效範圍。</exception>
		public static int BinarySearch<T>(this IList<T> list, int index, int count, T value, IComparer<T> comparer)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (index < 0 || count < 0 || index + count > list.Count)
				throw new ArgumentOutOfRangeException();
			Comparison<T> comparison;
			if (comparer == null)
			{
				if (!typeof(IComparable).IsAssignableFrom(typeof(T)))
					throw new ArgumentNullException("comparer");
				comparison = Compare<T>;
			}
			else
				comparison = comparer.Compare;

			//搜尋
			return BinarySearchInternal<T>(list, index, index + count, value, comparison);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <typeparam name="TItem">清單元素的型別。</typeparam>
		/// <typeparam name="TValue">搜尋目標的型別。</typeparam>
		/// <param name="list">指定的清單。</param>
		/// <param name="index">搜尋範圍的起始索引值。</param>
		/// <param name="count">搜尋範圍的元素個數。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="converter">將清單元素轉換成目標值的方法。</param>
		/// <param name="comparer">比較目標值大小的 IComparer&lt;TValue&gt; 介面，若目標值型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing) -或- converter 為 Null (Visual Basic 為 Nothing) -或- 目標值型別未實作 IComparable 介面，且 comparer 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index 或 count 超出有效範圍。</exception>
		public static int BinarySearch<TItem, TValue>(this IList<TItem> list, int index, int count, TValue value, Func<TItem, TValue> converter, IComparer<TValue> comparer)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (converter == null)
				throw new ArgumentNullException("converter");
			if (index < 0 || count < 0 || index + count > list.Count)
				throw new ArgumentOutOfRangeException();
			Comparison<TValue> comparison;
			if (comparer == null)
			{
				if (!typeof(IComparable).IsAssignableFrom(typeof(TValue)))
					throw new ArgumentNullException("comparer");
				comparison = Compare<TValue>;
			}
			else
				comparison = comparer.Compare;

			//搜尋
			return BinarySearchInternal<TItem, TValue>(list, index, index + count, value, converter, comparison);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <param name="list">指定的清單。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)。</exception>
		public static int BinarySearch<T>(this IList<T> list, T value) where T : IComparable
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (list.Count == 0)
				return -1;

			//搜尋
			return BinarySearch<T>(list, 0, list.Count, value, (Comparison<T>)null);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <typeparam name="TItem">清單元素的型別。</typeparam>
		/// <typeparam name="TValue">搜尋目標的型別。</typeparam>
		/// <param name="list">指定的清單。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="converter">將清單元素轉換成目標值的方法。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing) -或- converter 為 Null (Visual Basic 為 Nothing)。</exception>
		public static int BinarySearch<TItem, TValue>(this IList<TItem> list, TValue value, Func<TItem, TValue> converter) where TValue : IComparable
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (list.Count == 0)
				return -1;

			//搜尋
			return BinarySearch<TItem, TValue>(list, 0, list.Count, value, converter, (Comparison<TValue>)null);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <param name="list">指定的清單。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="comparison">比較元素大小的方法，若元素型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)，或元素型別未實作 IComparable 介面，且 comparison 為 Null (Visual Basic 為 Nothing)。</exception>
		public static int BinarySearch<T>(this IList<T> list, T value, Comparison<T> comparison)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (list.Count == 0)
				return -1;

			//搜尋
			return BinarySearch<T>(list, 0, list.Count, value, comparison);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <typeparam name="TItem">清單元素的型別。</typeparam>
		/// <typeparam name="TValue">搜尋目標的型別。</typeparam>
		/// <param name="list">指定的清單。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="converter">將清單元素轉換成目標值的方法。</param>
		/// <param name="comparison">比較目標值大小的方法，若目標值型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing) -或- converter 為 Null (Visual Basic 為 Nothing) -或- 目標值型別未實作 IComparable 介面，且 comparison 為 Null (Visual Basic 為 Nothing)。</exception>
		public static int BinarySearch<TItem, TValue>(this IList<TItem> list, TValue value, Func<TItem, TValue> converter, Comparison<TValue> comparison)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (list.Count == 0)
				return -1;

			//搜尋
			return BinarySearch<TItem, TValue>(list, 0, list.Count, value, converter, comparison);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <param name="list">指定的清單。</param>
		/// <param name="index">搜尋範圍的起始索引值。</param>
		/// <param name="count">搜尋範圍的元素個數。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index 或 count 超出有效範圍。</exception>
		public static int BinarySearch<T>(this IList<T> list, int index, int count, T value) where T : IComparable
		{
			return BinarySearch<T>(list, index, count, value, (Comparison<T>)null);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <typeparam name="TItem">清單元素的型別。</typeparam>
		/// <typeparam name="TValue">搜尋目標的型別。</typeparam>
		/// <param name="list">指定的清單。</param>
		/// <param name="index">搜尋範圍的起始索引值。</param>
		/// <param name="count">搜尋範圍的元素個數。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="converter">將清單元素轉換成目標值的方法。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing) -或- converter 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index 或 count 超出有效範圍。</exception>
		public static int BinarySearch<TItem, TValue>(this IList<TItem> list, int index, int count, TValue value, Func<TItem, TValue> converter) where TValue : IComparable
		{
			return BinarySearch<TItem, TValue>(list, index, index + count, value, converter, (Comparison<TValue>)null);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <param name="list">指定的清單。</param>
		/// <param name="index">搜尋範圍的起始索引值。</param>
		/// <param name="count">搜尋範圍的元素個數。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="comparison">比較元素大小的方法，若元素型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing)，或元素型別未實作 IComparable 介面，且 comparison 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index 或 count 超出有效範圍。</exception>
		public static int BinarySearch<T>(this IList<T> list, int index, int count, T value, Comparison<T> comparison)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (index < 0 || count < 0 || index + count > list.Count)
				throw new ArgumentOutOfRangeException();
			if (comparison == null)
			{
				if (!typeof(IComparable).IsAssignableFrom(typeof(T)))
					throw new ArgumentNullException("comparison");
				comparison = Compare<T>;
			}

			//搜尋
			return BinarySearchInternal<T>(list, index, index + count, value, comparison);
		}
		/// <summary>
		/// 在清單中使用二元搜尋法尋找指定值所在的位置。
		/// </summary>
		/// <typeparam name="TItem">清單元素的型別。</typeparam>
		/// <typeparam name="TValue">搜尋目標的型別。</typeparam>
		/// <param name="list">指定的清單。</param>
		/// <param name="index">搜尋範圍的起始索引值。</param>
		/// <param name="count">搜尋範圍的元素個數。</param>
		/// <param name="value">指定搜尋的值。</param>
		/// <param name="converter">將清單元素轉換成目標值的方法。</param>
		/// <param name="comparison">比較目標值大小的方法，若目標值型別已實作 IComparable 介面，則此參數可以為 Null (Visual Basic 為 Nothing)。</param>
		/// <returns>指定值在清單中的位置索引值。若該值不在清單中，則傳回清單中第一個大於或等於該值之值的位置索引值位元補數。</returns>
		/// <exception cref="ArgumentNullException">list 為 Null (Visual Basic 為 Nothing) -或- converter 為 Null (Visual Basic 為 Nothing) -或- 目標值型別未實作 IComparable 介面，且 comparison 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index 或 count 超出有效範圍。</exception>
		public static int BinarySearch<TItem, TValue>(this IList<TItem> list, int index, int count, TValue value, Func<TItem, TValue> converter, Comparison<TValue> comparison)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (converter == null)
				throw new ArgumentNullException("converter");
			if (index < 0 || count < 0 || index + count > list.Count)
				throw new ArgumentOutOfRangeException();
			if (comparison == null)
			{
				if (!typeof(IComparable).IsAssignableFrom(typeof(TValue)))
					throw new ArgumentNullException("comparison");
				comparison = Compare<TValue>;
			}

			//搜尋
			return BinarySearchInternal<TItem, TValue>(list, index, index + count, value, converter, comparison);
		}
		#endregion
		#region BinarySearchInternal
		static int BinarySearchInternal<T>(IList<T> list, int startIndex, int endIndex, T value, Comparison<T> comparison)
		{
			//比對中間的值
			if (startIndex >= endIndex)
				return ~startIndex;
			int middleIndex = (startIndex + endIndex) >> 1;
			int result = comparison(list[middleIndex], value);
			if (result == 0)
				return middleIndex;

			//搜尋左右側
			if (result > 0)
			{
				//確認是否已搜尋完畢
				if (endIndex - startIndex == 1)
					return ~startIndex;

				//搜尋左側
				return BinarySearchInternal<T>(list, startIndex, middleIndex, value, comparison);
			}
			else
			{
				//確認是否已搜尋完畢
				if (endIndex - startIndex <= 2)
					return ~endIndex;

				//搜尋右側
				return BinarySearchInternal<T>(list, middleIndex + 1, endIndex, value, comparison);
			}
		}
		static int BinarySearchInternal<TItem, TValue>(IList<TItem> list, int startIndex, int endIndex, TValue value, Func<TItem, TValue> converter, Comparison<TValue> comparison)
		{
			//比對中間的值
			if (startIndex >= endIndex)
				return ~startIndex;
			int middleIndex = (startIndex + endIndex) >> 1;
			TValue middleValue = converter(list[middleIndex]);
			int result = comparison(middleValue, value);
			if (result == 0)
				return middleIndex;

			//搜尋左右側
			if (result > 0)
			{
				//確認是否已搜尋完畢
				if (endIndex - startIndex == 1)
					return ~startIndex;

				//搜尋左側
				return BinarySearchInternal<TItem, TValue>(list, startIndex, middleIndex, value, converter, comparison);
			}
			else
			{
				//確認是否已搜尋完畢
				if (endIndex - startIndex <= 2)
					return ~endIndex;

				//搜尋右側
				return BinarySearchInternal<TItem, TValue>(list, middleIndex + 1, endIndex, value, converter, comparison);
			}
		}
		#endregion
		#region ChangeByteOrdering
		/// <summary>
		/// 將 Byte 陣列視為其他型別的一維陣列，並轉換 Byte-Ordering。
		/// </summary>
		/// <param name="array">Byte 陣列指標。</param>
		/// <param name="startIndex">轉換的起始索引位置。</param>
		/// <param name="length">轉換的位元組數。</param>
		/// <param name="sizeOfElement">每個元素的位元組長度。</param>
		/// <exception cref="ArgumentException">length 不是 sizeOfElement 的整數倍。</exception>
		/// <exception cref="ArgumentNullException">array 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index、length 或 sizeOfElement 超出有效範圍。</exception>
		public static void ChangeByteOrdering(byte* array, int startIndex, int length, int sizeOfElement)
		{
			//確認參數
			if (array == null)
				throw new ArgumentException();
			if (startIndex < 0 || length < 0 || sizeOfElement <= 0)
				throw new ArgumentOutOfRangeException();
			if ((length % sizeOfElement) != 0)
				throw new ArgumentException();
			if (length == 0 || sizeOfElement == 1)
				return;

			//轉換 Byte-Ordering
			array += startIndex;
			int elementCount = (length / sizeOfElement);
			byte temp;
			switch (sizeOfElement)
			{
				case 2:
					for (; elementCount > 0; --elementCount, array += 2)
					{
						temp = array[0];
						array[0] = array[1];
						array[1] = temp;
					}
					break;
				case 4:
					for (; elementCount > 0; --elementCount, array += 4)
					{
						temp = array[0];
						array[0] = array[3];
						array[3] = temp;
						temp = array[1];
						array[1] = array[2];
						array[2] = temp;
					}
					break;
				case 8:
					for (; elementCount > 0; --elementCount, array += 8)
					{
						temp = array[0];
						array[0] = array[7];
						array[7] = temp;
						temp = array[1];
						array[1] = array[6];
						array[6] = temp;
						temp = array[2];
						array[2] = array[5];
						array[5] = temp;
						temp = array[3];
						array[3] = array[4];
						array[4] = temp;
					}
					break;
				default:
					{
						int numOfExchangeBytes = (sizeOfElement / 2);
						for (; elementCount > 0; --elementCount, array += sizeOfElement)
						{
							for (int i = 0; i < numOfExchangeBytes; ++i)
							{
								temp = array[i];
								array[i] = array[sizeOfElement - i - 1];
								array[sizeOfElement - i - 1] = temp;
							}
						}
					}
					break;
			}
		}
		/// <summary>
		/// 將 Byte 陣列視為其他型別的一維陣列，並轉換 Byte-Ordering。
		/// </summary>
		/// <param name="array">Byte 陣列。</param>
		/// <param name="index">轉換的起始索引位置。</param>
		/// <param name="length">轉換的位元組數。</param>
		/// <param name="sizeOfElement">每個元素的位元組長度。</param>
		/// <exception cref="ArgumentException">length 不是 sizeOfElement 的整數倍。</exception>
		/// <exception cref="ArgumentNullException">array 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentOutOfRangeException">index、length 或 sizeOfElement 超出有效範圍。</exception>
		public static void ChangeByteOrdering(this byte[] array, int index, int length, int sizeOfElement)
		{
			//確認參數
			if (array == null)
				throw new ArgumentNullException("array");
			if (index < 0 || index + length > array.Length || length < 0 || sizeOfElement <= 0)
				throw new ArgumentOutOfRangeException();

			//轉換 Byte-Ordering
			fixed (byte* ptr = array)
				ChangeByteOrdering(ptr, index, length, sizeOfElement);
		}
		#endregion
		#region CloneAllElements
		/// <summary>
		/// 為集合中的所有元素建立複本，並放置於新的陣列中。
		/// </summary>
		/// <typeparam name="T">集合元素型別。</typeparam>
		/// <param name="collection">提供元素的集合。</param>
		/// <returns>放置元素複本的陣列。</returns>
		/// <exception cref="ArgumentNullException">collection 為 Null (Visual Basic 為 Nothing)。</exception>
		public static T[] CloneAllElements<T>(this IEnumerable<T> collection)
		{
			//確認參數
			if (collection == null)
				throw new ArgumentNullException("collection");

			//複製集合
			T[] array;
			ICollection<T> collectionInterface = (collection as ICollection<T>);
			if (collectionInterface != null)
			{
				//建立陣列
				array = new T[collectionInterface.Count];

				//建立元素複本
				IList<T> list = (collection as IList<T>);
				if (list != null)
				{
					for (int index = array.Length - 1; index >= 0; --index)
					{
						T element = list[index];
						array[index] = (element is ICloneable ? (T)((ICloneable)element).Clone() : element);
					}
				}
				else
				{
					int index = array.Length - 1;
					foreach (T element in collection)
						array[index--] = (element is ICloneable ? (T)((ICloneable)element).Clone() : element);
				}
			}
			else
			{
				List<T> list = new List<T>();
				foreach (T element in collection)
					list.Add((element is ICloneable ? (T)((ICloneable)element).Clone() : element));
				array = list.ToArray();
			}
			return array;
		}
		#endregion
		#region Compare
		static int Compare<T>(T x, T y)
		{
			if (x is IComparable)
				return (x as IComparable).CompareTo(y);
			if (y is IComparable)
				return -(y as IComparable).CompareTo(x);
			return 0;
		}
		#endregion
		#region Concat
		/// <summary>
		/// 合併兩個一維陣列。
		/// </summary>
		/// <param name="array1">第一個一維陣列，合併後將放在新陣列的前段。</param>
		/// <param name="array2">第二個一維陣列，合併後將放在新陣列的後段。</param>
		/// <returns>合併後的一維陣列。</returns>
		public static T[] Concat<T>(this T[] array1, T[] array2)
		{
			if (array1 != null)
			{
				if (array2 != null)
				{
					int length1 = array1.Length;
					int length2 = array2.Length;
					T[] newArray = new T[length1 + length2];
					array1.CopyTo(newArray, 0);
					array2.CopyTo(newArray, length1);
					return newArray;
				}
				return array1.Clone() as T[];
			}
			else if (array2 != null)
				return array2.Clone() as T[];
			return null;
		}
		#endregion
		#region Convert2BytesValueArray
		static void Convert2BytesValueArray(void* src, byte[] dest, BitConverter bitConverter, int srcElementCount)
		{
			//確認參數
			if (bitConverter == null)
				bitConverter = BitConverter.System;
			if (srcElementCount < 0)
				throw new ArgumentOutOfRangeException();
			if (srcElementCount == 0)
				return;

			//轉換
			Marshal.Copy((IntPtr)src, dest, 0, srcElementCount * 2);
			if (!bitConverter.IsSystemByteOrdering)
				ChangeByteOrdering(dest, 0, srcElementCount * 2, 2);
		}
		static void Convert2BytesValueArray(byte[] src, void* dest, BitConverter bitConverter, int length)
		{
			//確認參數
			if (bitConverter == null)
				bitConverter = BitConverter.System;
			if (length < 0)
				throw new ArgumentOutOfRangeException();
			if (length == 0)
				return;

			//轉換
			Marshal.Copy(src, 0, (IntPtr)dest, length * 2);
			if (!bitConverter.IsSystemByteOrdering)
				ChangeByteOrdering((byte*)dest, 0, length * 2, 2);
		}
		#endregion
		#region Convert4BytesValueArray
		static void Convert4BytesValueArray(void* src, byte[] dest, BitConverter bitConverter, int srcElementCount)
		{
			//確認參數
			if (bitConverter == null)
				bitConverter = BitConverter.System;
			if (srcElementCount < 0)
				throw new ArgumentOutOfRangeException();
			if (srcElementCount == 0)
				return;

			//轉換
			Marshal.Copy((IntPtr)src, dest, 0, srcElementCount * 4);
			if (!bitConverter.IsSystemByteOrdering)
				ChangeByteOrdering(dest, 0, srcElementCount * 4, 4);
		}
		static void Convert4BytesValueArray(byte[] src, void* dest, BitConverter bitConverter, int length)
		{
			//確認參數
			if (bitConverter == null)
				bitConverter = BitConverter.System;
			if (length < 0)
				throw new ArgumentOutOfRangeException();
			if (length == 0)
				return;

			//轉換
			Marshal.Copy(src, 0, (IntPtr)dest, length * 4);
			if (!bitConverter.IsSystemByteOrdering)
				ChangeByteOrdering((byte*)dest, 0, length * 4, 4);
		}
		#endregion
		#region Convert8BytesValueArray
		static void Convert8BytesValueArray(void* src, byte[] dest, BitConverter bitConverter, int srcElementCount)
		{
			//確認參數
			if (bitConverter == null)
				bitConverter = BitConverter.System;
			if (srcElementCount < 0)
				throw new ArgumentOutOfRangeException();
			if (srcElementCount == 0)
				return;

			//轉換
			Marshal.Copy((IntPtr)src, dest, 0, srcElementCount * 8);
			if (!bitConverter.IsSystemByteOrdering)
				ChangeByteOrdering(dest, 0, srcElementCount * 8, 8);
		}
		static void Convert8BytesValueArray(byte[] src, void* dest, BitConverter bitConverter, int length)
		{
			//確認參數
			if (bitConverter == null)
				bitConverter = BitConverter.System;
			if (length < 0)
				throw new ArgumentOutOfRangeException();
			if (length == 0)
				return;

			//轉換
			Marshal.Copy(src, 0, (IntPtr)dest, length * 8);
			if (!bitConverter.IsSystemByteOrdering)
				ChangeByteOrdering((byte*)dest, 0, length * 8, 8);
		}
		#endregion
		#region CopyTo
		/// <summary>
		/// 將多個項目複製至指定的集合中。
		/// </summary>
		/// <typeparam name="T">項目型別。</typeparam>
		/// <param name="values">欲複製至集合的項目。</param>
		/// <param name="collection">指定的集合。</param>
		/// <exception cref="ArgumentNullException">collection 為 Null (Visual Basic 為 Nothing)。</exception>
		public static void CopyTo<T>(this IEnumerable<T> values, ICollection<T> collection)
		{
			//確認參數
			if (collection == null)
				throw new ArgumentNullException("collection");
			if (values == null)
				return;

			//複製資料
			if (collection is List<T>)
				(collection as List<T>).AddRange(values);
			else
			{
				foreach (T value in values)
					collection.Add(value);
			}
		}
		#endregion
		#region GetAsEnumerable
		/// <summary>
		/// 將指定的 System.Collections.IEnumerable 介面轉成 System.Collections.Generic.IEnumerable&lt;T&gt; 介面。
		/// </summary>
		/// <typeparam name="T">指定的型別。</typeparam>
		/// <param name="enumerable">System.Collections.IEnumerable 介面。</param>
		/// <returns>System.Collections.Generic.IEnumerable&lt;T&gt; 介面。</returns>
		/// <exception cref="ArgumentNullException">enumerable 為 Null (Visual Basic 為 Nothing)。</exception>
		public static IEnumerable<T> GetAsEnumerable<T>(this IEnumerable enumerable)
		{
			//確認參數
			if (enumerable == null)
				throw new ArgumentNullException("enumerable");

			//取得 IEnumerable<T>
			IEnumerable<T> enumerableT = (enumerable as IEnumerable<T>);
			if (enumerableT == null)
				return new EnumerableCollection<T>(enumerable);
			return enumerableT;
		}
		#endregion
		#region GetEnumerator
		/// <summary>
		/// 取得指定型別的 System.Collections.Generic.IEnumerator&lt;T&gt;。
		/// </summary>
		/// <typeparam name="T">指定的型別。</typeparam>
		/// <param name="enumerable">System.Collections.IEnumerable 介面。</param>
		/// <returns>System.Collections.Generic.IEnumerator&lt;T&gt; 介面。</returns>
		/// <exception cref="ArgumentNullException">enumerable 為 Null (Visual Basic 為 Nothing)。</exception>
		public static IEnumerator<T> GetEnumerator<T>(this IEnumerable enumerable)
		{
			//確認參數
			if (enumerable == null)
				throw new ArgumentNullException("enumerable");
			
			//取得 Enumerator
			IEnumerable<T> enumerableT = (enumerable as IEnumerable<T>);
			if (enumerableT == null)
				return new Enumerator<T>(enumerable.GetEnumerator());
			return enumerableT.GetEnumerator();
		}
		#endregion
		#region Remove
		/// <summary>
		/// 移除所有符合條件的元素。
		/// </summary>
		/// <typeparam name="T">集合元素的型別。</typeparam>
		/// <param name="list">要移除元素的集合。</param>
		/// <param name="predicate">確認元素是否符合條件的方法。</param>
		/// <returns>移除的元素個數。</returns>
		/// <exception cref="ArgumentNullException">list 或 predicate 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">list 為唯讀集合。</exception>
		public static int Remove<T>(this IList<T> list, Predicate<T> predicate)
		{
			//確認參數
			if (list == null)
				throw new ArgumentNullException("list");
			if (predicate == null)
				throw new ArgumentNullException("predicate");
			if (list.IsReadOnly)
				throw new InvalidOperationException();
			
			//移除項目
			int count = 0;
			for (int i = list.Count - 1; i >= 0; --i)
			{
				if (predicate(list[i]))
				{
					list.RemoveAt(i);
					++count;
				}
			}

			//完成
			return count;
		}
		#endregion
		#region ToBytes
		/// <summary>
		/// 將 8 位元整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">8 位元整數陣列。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this sbyte[] array)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount];
			fixed (sbyte* ptr = array)
				Marshal.Copy((IntPtr)ptr, bytes, 0, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將 16 位元整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">16 位元整數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this short[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 2];
			fixed (short* ptr = array)
				Convert2BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將 16 位元無符號整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">16 位元無符號整數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this ushort[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 2];
			fixed (ushort* ptr = array)
				Convert2BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將 32 位元整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">32 位元整數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this int[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 4];
			fixed (int* ptr = array)
				Convert4BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將 32 位元無符號整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">32 位元無符號整數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this uint[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 4];
			fixed (uint* ptr = array)
				Convert4BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將單精準浮點數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">單精準浮點數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this float[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 4];
			fixed (float* ptr = array)
				Convert4BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將 64 位元整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">64 位元整數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this long[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 8];
			fixed (long* ptr = array)
				Convert8BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將 64 位元無符號整數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">64 位元無符號整數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this ulong[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 8];
			fixed (ulong* ptr = array)
				Convert8BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		/// <summary>
		/// 將倍精準浮點數陣列轉換成位元組陣列。
		/// </summary>
		/// <param name="array">倍精準浮點數陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <returns>位元組陣列。</returns>
		public static byte[] ToBytes(this double[] array, BitConverter bitConverter)
		{
			//確認參數
			if (array == null)
				return null;

			//轉換
			int elementCount = array.Length;
			byte[] bytes = new byte[elementCount * 8];
			fixed (double* ptr = array)
				Convert8BytesValueArray((byte*)ptr, bytes, bitConverter, elementCount);
			return bytes;
		}
		#endregion
		#region ToDoubleArray
		/// <summary>
		/// 將位元組陣列轉換成倍精準浮點數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">倍精準浮點數陣列長度。</param>
		/// <returns>倍精準浮點數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static double[] ToDoubleArray(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			double[] array = new double[elementCount];
			fixed (double* ptr = array)
				Convert8BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToInt16Array
		/// <summary>
		/// 將位元組陣列轉換成 16 位元整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">整數陣列長度。</param>
		/// <returns>16 位元整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static short[] ToInt16Array(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			short[] array = new short[elementCount];
			fixed (short* ptr = array)
				Convert2BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToInt32Array
		/// <summary>
		/// 將位元組陣列轉換成 32 位元整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">整數陣列長度。</param>
		/// <returns>32 位元整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static int[] ToInt32Array(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			int[] array = new int[elementCount];
			fixed (int* ptr = array)
				Convert4BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToInt64Array
		/// <summary>
		/// 將位元組陣列轉換成 64 位元整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">整數陣列長度。</param>
		/// <returns>64 位元整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static long[] ToInt64Array(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			long[] array = new long[elementCount];
			fixed (long* ptr = array)
				Convert8BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToSByteArray
		/// <summary>
		/// 將位元組陣列轉換成 8 位元整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="elementCount">整數陣列長度。</param>
		/// <returns>8 位元整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static sbyte[] ToSByteArray(this byte[] bytes, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			sbyte[] array = new sbyte[elementCount];
			fixed (sbyte* ptr = array)
				Marshal.Copy(bytes, 0, (IntPtr)ptr, elementCount);
			return array;
		}
		#endregion
		#region ToSingleArray
		/// <summary>
		/// 將位元組陣列轉換成單精準浮點數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">單精準浮點數陣列長度。</param>
		/// <returns>單精準浮點數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static float[] ToSingleArray(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			float[] array = new float[elementCount];
			fixed (float* ptr = array)
				Convert4BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToUInt16Array
		/// <summary>
		/// 將位元組陣列轉換成 16 位元無符號整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">無符號整數陣列長度。</param>
		/// <returns>16 位元無符號整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static ushort[] ToUInt16Array(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			ushort[] array = new ushort[elementCount];
			fixed (ushort* ptr = array)
				Convert2BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToUInt32Array
		/// <summary>
		/// 將位元組陣列轉換成 32 位元無符號整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">無符號整數陣列長度。</param>
		/// <returns>32 位元無符號整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static uint[] ToUInt32Array(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			uint[] array = new uint[elementCount];
			fixed (uint* ptr = array)
				Convert4BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region ToUInt64Array
		/// <summary>
		/// 將位元組陣列轉換成 64 位元無符號整數陣列。
		/// </summary>
		/// <param name="bytes">位元組陣列。</param>
		/// <param name="bitConverter">提供位元組轉換的 BitConverter，Null (Visual Basic 為 Nothing) 表示使用系統的位元組順序。</param>
		/// <param name="elementCount">無符號整數陣列長度。</param>
		/// <returns>64 位元無符號整數陣列。</returns>
		/// <exception cref="ArgumentOutOfRangeException">elementCount 為負值。</exception>
		public static ulong[] ToUInt64Array(this byte[] bytes, BitConverter bitConverter, int elementCount)
		{
			//確認參數
			if (bytes == null)
				return null;
			if (elementCount < 0)
				throw new ArgumentOutOfRangeException();

			//轉換成陣列
			ulong[] array = new ulong[elementCount];
			fixed (ulong* ptr = array)
				Convert8BytesValueArray(bytes, ptr, bitConverter, elementCount);
			return array;
		}
		#endregion
		#region TryConvertTo
		/// <summary>
		/// 嘗試將指定的一維陣列轉換成指定型別的一維陣列。
		/// </summary>
		/// <typeparam name="T">指定的陣列元素型別。</typeparam>
		/// <param name="array">指定的一維陣列。</param>
		/// <param name="newArray">轉換後的一維陣列。</param>
		/// <returns>True 表示轉換成功，False 表示轉換失敗。</returns>
		public static bool TryConvertTo<T>(this Array array, out T[] newArray)
		{
			//確認參數
			if (array == null)
			{
				newArray = null;
				return true;
			}
			if (array.Rank != 1)
			{
				newArray = null;
				return false;
			}

			//轉換型別
			int length = array.Length;
			newArray = new T[length];
			for (int i = length - 1; i >= 0; --i)
			{
				if (!array.GetValue(i).TryCast<T>(out newArray[i]))
				{
					newArray = null;
					return false;
				}
			}

			//轉換完成
			return true;
		}
		#endregion
	}
}
